<!DOCTYPE html>
<head>  
 <meta charset="UTF-8">  
 <meta name="viewport" content="width=device-width, initial-scale=1.0">  
 <title>Apidev是一个专注于API开发和管理的平台，旨在为开发者提供高效的API解决方案和工具。</title>
  <meta name="keywords" content="接口开发 接口文档 接口调试 API管理工具">
  <meta name="description"content="Apidev是一个专注于API开发和管理的平台，旨在为开发者提供高效的API解决方案和工具,非常适合IT团队的API开发工具、技术文档开发工具。">

 <link rel="stylesheet" href="#(path)/assets/apidev/lib/layui_exts/mouseRightMenu/mouseRightMenu.css" />
<link rel="stylesheet" href="#(path)/assets/apidev/lib/layui-v2.9.18/layui/css/layui.css" media="all" /> 

<style type="text/css">
	.layui-colla-content {
	    color: #333333eb;
	}
	.layui-colla-content, .layui-colla-item1{
		border-color: #eee;
    	border-top-width: 1px;
    	border-top-style: solid;
 }
 #apiTable-toolbar-setRowChecked,#shortcutTable-toolbar-setRowChecked{
 	border: 1px solid #eee;
 	padding:10px;
 	border-bottom:none;
 }
/* api css start*/
.api-tab-header{
	width:265px;
	background:#ececee;
}
.api-tab-header .layui-btn.layui-this{background:#ffffff;border:1px solid #ccc;}
.api-tab-body>div{display: none;padding-top:10px}
.layui-btn-container .layui-btn {
    margin-right: 0px;
    padding-right:10px;
    padding-left:12px;
    border-color:#ececee;
 }
 .layui-anim dd{  
  color:#11ab11;
}

.layui-anim dd:nth-child(2) {  
   color:#ed5d11;
}  

.layui-anim dd:nth-child(3) {  
  color: #0f85df;   
}  

.layui-anim dd:nth-child(4) {  
  color: #c50101;
}  

.layui-anim dd:nth-child(5) {  
  color: #0f85df;  
}  

.layui-anim dd:nth-child(6) {  
  color: #0f85df;  
}  

.layui-anim dd:nth-child(7) {    
	color: #0f85df;  
}  
input[value="GET"],
input[value="TRACE"],
input[value="PATCH"] {   
  color: #11ab11;  
}  

/* POST 请求 */   
input[value="POST"] {  
  color: #ed5d11;  
}  

/* DELETE 请求 */  
input[value="DELETE"]{
	color:#c50101;
}

input[value="PULL"],
input[value="HEAD"],
input[value="CONNECT"],
input[value="OPTIONS"] {  
  color: #0f85df; 
}  
#title-input:focus {
	border: none; 
	border-bottom: 1px solid #ccc!important;
    background-color: #ccc;
}
.layui-form-onswitch, .layui-form-switch {
	border-color: #d2d2d2;
	margin-left: 10px;
	margin-top: 5px;
}
</style>
<link id="layui_theme_css" rel="stylesheet">
<link rel="stylesheet" href="#(path)/assets/apidev/css/index.css" />
<style>
	.tree-node-title .layui-icon-more {
		right:15px;
		margin-top:-16px;
		padding-right:15px;
	}
</style>
</head>  
<body>  
<div class="layui-row con">
  <div class="layui-col-xs12 layui-col-sm6 layui-col-md3 layui-col-md-offset1 layui-form" style="overflow: auto;max-height:100%;padding:10px;">
  	<div class="layui-form-item">
  		<div class="layui-form layui-input-wrap" style="width: 75%;float: left">
			<div class="layui-input-prefix">
				<i class="layui-icon layui-icon-search"></i>
			</div>
			<input type="text" name="keyword" lay-affix="clear" placeholder="搜索..." autocomplete="off"class="layui-input" onblur="search()" oninput="search()">
		</div>
		<div>
			<input id="switchTheme" type="checkbox" lay-skin="switch"lay-filter="switchTheme" title="暗|亮">
		</div>
	</div>
    <div id="tree-container" style="overflow: auto;max-height:calc(100vh - 70px);"></div>
  </div>
  <div class="layui-col-md8">
    <div class="layui-col-xs12 layui-col-sm6 layui-col-md10 body-right">
		<div class="layui-tab" lay-filter="tab-handle" lay-allowclose="true">
			<ul class="layui-tab-title tab-handle">
			</ul>
			<div class="layui-tab-content" style="overflow: auto;max-height:calc(100vh - 80px);padding-bottom:5px;"></div>
		</div>
	</div>
  </div>
</div>

  
<script src="#(path)/assets/apidev/lib/jquery/jquery-2.1.4.min.js"></script>
<script src="#(path)/assets/apidev/lib/jquery/jquery.form.js" type="text/javascript" ></script>
<script src="#(path)/assets/apidev/lib/layui-v2.9.18/layui/layui.js" type="text/javascript"></script>
<script>  
var thisId = '';
var treeData = #(tree_data??[]);
var mouseRightMenu;
var element = layui.element;

var titleKeyword='';
// 右键菜单组件
layui.config({base: '#(path)/assets/apidev/lib/layui_exts/mouseRightMenu/'});
layui.use(['mouseRightMenu'], function(){
	mouseRightMenu = layui.mouseRightMenu;
});

//设置主题
document.addEventListener("DOMContentLoaded", function() {  
	  var checked=localStorage.getItem("layui_theme_css");
	  tabTheme(checked);
});  
layui.form.on('switch(switchTheme)', function(data){
	  localStorage.setItem("layui_theme_css",this.checked);	
	  tabTheme(this.checked);
});

// 初始化目录树
loadTree(treeData,true,'tree-container');

//搜索
function search(){
	titleKeyword = $("input[name=keyword]").val();
	 // 接口树
	var filteredData = treeData.map(node => filterByTitleKeyword(node, titleKeyword)).filter(item => item !== null); 
	if(titleKeyword==''){
		filteredData=treeData;
	}
	loadTree(filteredData,true,'tree-container');
	bindDownloadFunc();
}

//通过关键词过滤
function filterByTitleKeyword(node, titleKeyword, isParentOpened = false) {  
    if (!node || typeof node !== 'object') return null;  

    // 初始化当前节点的 isOpen 属性  
    const currentIsOpen = isParentOpened || (node.title && node.title.includes(titleKeyword) && titleKeyword !='');
    
    // 过滤子节点  
    if (Array.isArray(node.children)) {  
        const filteredChildren = node.children  
            .map(child => filterByTitleKeyword(child, titleKeyword, currentIsOpen))  
            .filter(child => child !== null);  

        // 如果当前节点有匹配标题的子节点，或者当前节点的标题包含关键词  
        if (filteredChildren.length > 0 || currentIsOpen) {  
            return {  
                ...node,  
                isopen: titleKeyword==''?false:true, // 设置当前节点的 isOpen 属性为 true  
                children: filteredChildren.length > 0 ? filteredChildren : undefined,  
            };  
        }  
    }  

    // 返回当前节点本身如果它的标题包含关键词  
    if (node.title && node.title.includes(titleKeyword)) {  
        return {  
            ...node,  
            isopen: titleKeyword==''?false:true, // 设置当前节点的 isOpen 属性为 true  
        };  
    }  

    return null; // 返回 null，如果没有匹配的条目  
}  


function tabTheme(checked){
	if(checked==true||checked=='true'){
		  // 设置为深色主题
		  document.getElementById('layui_theme_css').setAttribute('href','#(path)/assets/apidev/lib/layui-theme-dark/layui-theme-dark.css');
		  document.getElementById("switchTheme").checked = true; 
		  layui.form.render(); 
	  }else{
		  // 恢复浅色主题
		  document.getElementById('layui_theme_css').removeAttribute('href');
	 }
}

// 重新渲染tree
function loadTree(data,isFirst,divId){
	  $('#'+divId).html(createTree(data,isFirst,divId));
}

	// 创建树形菜单  
  function createTree(data,isFirst,divId) { 
      if(data==undefined) 
          return '';
      
  	var html = '';  
  	var display = data[0] && data[0].isopen ? 'block' : 'none';
  	
  	if(isFirst)
      	display = 'block';
		
      if(isFirst){
      	html = `<ul class="tree-root">`;  
      }else{
      	html = `<ul class="children" style="display: ${display}">`;  
       }
      // 循环节点
      data.forEach(node => {  
      	var hasChildren = node.children && node.children.length > 0;  
          var iconClass = hasChildren && !node.children[0].isopen ? 'icon right' : 'icon down';  
          if(isFirst)
          	iconClass = 'icon down';
      	// 创建节点
          html += `<li class="tree-node"><div data-id="${node.id}"
              onclick="toggleNode(event, this,'${divId}')" class="tree-node-title ${thisId == node.id?'active':''}">`; 
          // 子节点数量    		
          var subNodeNum = node.children && node.children.length>0 ?  '（'+node.children.length+'）' : '';
          // 节点前面图标
          if(node.type=='menu'){ // 目录
              if(hasChildren)
          		html += `<i class=" layui-icon layui-icon-right ${iconClass}" onclick="toggleRightIcon(event, this)"></i>`;
          	html += `<i class="layui-icon layui-icon-export" style="padding-right:2px"></i>`;
          	if(subNodeNum=='')
          		subNodeNum='（0）';
          } else if(node.type=='api' || node.type == 'link'){ // 接口
          	if(hasChildren)
          		html += `<i class=" layui-icon layui-icon-right ${iconClass}" onclick="toggleRightIcon(event, this)"></i>`;
               if(node.request_mode){
	             	html += `<span class="${node.request_mode}">${node.request_mode}</span>`;
	             } else {
	    			html += `<span class="GET">GET</span>`;
	    		 }
          } else if(node.type=='demo'){ // 用例
          	html += `<i class="layui-icon layui-icon-log" title="接口用例"></i>`;
          }
          // 节点名称、更多图标
          html +=`<span>${node.title}${subNodeNum}</span><i data-id="${node.id}" class="layui-icon layui-icon-more1 tree-menu-more1 ${node.type=='demo'?'layui-hide':''}"></i></div>`;  
			// 递归创建子节点
          if (hasChildren) {
              html += createTree(node.children,false,divId);  
          }  

          html += `</li>`;     
      });  

      html += `</ul>`;  
      return html;  
  }  

  // 接口树点击图标
  function toggleRightIcon(event,_this){
  	event.stopPropagation();         
      const childrenUl = _this.parentNode.parentNode.querySelector('ul.children');  

      // 获取节点 
      if (childrenUl) {
          const isExpanded = childrenUl.style.display === 'block';  
          childrenUl.style.display = isExpanded ? 'none' : 'block';  
          _this.classList.toggle('right', isExpanded);  
          _this.classList.toggle('down', !isExpanded);  
      }
  }

//切换节点显示和隐藏  
  function toggleNode(event,_this,divId) {
      event.stopPropagation(); 
   	// 移除其他节点的活动样式  
      const activeNodes = document.querySelectorAll('.active');  
      activeNodes.forEach(node => node.classList.remove('active'));  

      // 设置当前节点为活动  
      _this.classList.add('active');
      
      const childrenUl = _this.parentNode.querySelector('ul.children');  
      const icon = _this.querySelector('.icon');  
      
      // 获取节点 ID 并显示  
      const nodeId = _this.getAttribute('data-id');
      var nodeData;
      var treeType = '1';
      if(divId=='tree-container') {
      	nodeData = findNodeById(treeData[0], nodeId);
      }else{
      	nodeData = findNodeById(linkData[0], nodeId);
      	treeType = '2';
      }
      
      var title = '';  
      if(nodeData.type=='menu'){
			title='<i class="layui-icon layui-icon-export"></i>';
      }else if(nodeData.type=='demo'){
      	title='<i class="layui-icon layui-icon-log"></i>';
      }else if(nodeData.type=='link'){
      	title='<i class="layui-icon layui-icon-senior" style="color:#409EFF"></i>';
      }else{
          var mode=nodeData.request_mode||'GET';
      	title='<span class="'+mode+'">'+mode+'</span>'
      }
      var li=$('li[lay-id='+nodeId+']');
      thisId = nodeId;
		if(nodeData.type=='menu'){
			if (childrenUl) {
	            const isExpanded = childrenUl.style.display === 'block';  
	            childrenUl.style.display = isExpanded ? 'none' : 'block';  
	            icon.classList.toggle('right', isExpanded);  
	            icon.classList.toggle('down', !isExpanded);  
	        }  
		}else{
			// 显示在右侧tab
	        clickApi(nodeData.id,title+nodeData.title); 
	        if (li.length>0 && childrenUl) {
	            const isExpanded = childrenUl.style.display === 'block';  
	            childrenUl.style.display = isExpanded ? 'none' : 'block';  
	            icon.classList.toggle('right', isExpanded);  
	            icon.classList.toggle('down', !isExpanded);  
	        }  
		}
  }  

//通过id查找api对象
  function findNodeById(node, id) {  
      if (!node) return null;  
      
      // 检查当前节点是否是目标节点  
      if (node.id === id) {  
          return node;  
      }  

      // 如果有子节点，递归查找  
      if (Array.isArray(node.children)) {  
          for (var child of node.children) {  
              const result = findNodeById(child, id);  
              if (result) {  
                  return result; // 找到后返回  
              }  
          }  
      }  

      return null; // 没有找到，返回 null  
  }  

	  // 接口菜单点击事件
	  function clickApi(id,title){
			// 定义要查找的lay-id值
			var li=$('li[lay-id='+id+']');
			if(li.length>0){
				element.tabChange('tab-handle', id); // 切换到标签
			}else{
				if($('.tab-handle li').length>=4){
			 		var tabId=$('.tab-handle li').eq(0).attr('lay-id');
			        tabClose(tabId);
				}
				$.ajax({
					url:'#(path)#(apiActionKey)/doc',
					type:'POST',
					data:{id:id,title:title},
					success:function(html){
						element.tabAdd('tab-handle', {
					        title: title,
					        content: html,
					        id: id,
					        change: true // 是否添加完毕后即自动切换
					    });
					    
						bindTabRightMenu();
						
						layui.code({
						    elem: '.code-demo-'+thisId,
						    langMarker:true
						 });
					}
				});
				
			}
			
		}

	  layui.element.on('tab(tab-handle)', function(data){
		  thisId=data.id;
		  const activeNodes = document.querySelectorAll('.active');  
	      activeNodes.forEach(node => node.classList.remove('active'));  
	      $('div[data-id='+thisId+']').addClass('active');
	});

	// tab导航右键菜单
		function bindTabRightMenu(){
			$('.tab-handle li').off("contextmenu");
			//右键目录菜单
			$('.tab-handle li').bind("contextmenu",function(e){
				var id=$(this).attr('lay-id');
				var data = {menuId:id}
				var menu_data=[
					{'data':data,'type':'closeTab','title':'关闭当前标签','icon':'layui-icon-close'},
					{'data':data,'type':'closeOtherTabs','title':'关闭其它标签','icon':'layui-icon-error'},
					{'data':data,'type':'closeAllTabs','title':'关闭全部标签','icon':'layui-icon-close-fill'},
				]
				mouseRightMenu.open(menu_data,false,function(d){
					var menuId=d.data.menuId;
					if(d.type=='closeTab'){
		 	 			tabClose(menuId);
			 		} else if(d.type=='closeOtherTabs'){
			 			$('.layui-tab-title li').each(function() {  
				 			if($(this).attr('lay-id')!=menuId){
				 				var id=$(this).attr('lay-id');
				 	 			tabClose(id); 
				 			}
				        }); 
			 	 	} else if(d.type=='closeAllTabs'){
			 	 		$('.layui-tab-title li').each(function() {  
				 	 		var id=$(this).attr('lay-id');
			 	 			tabClose(id);
				         }); 
			 	 	}
				})
				return false;
			});
			
		}

		// 关闭tab
		function tabClose(tabId){
			element.tabDelete('tab-handle', tabId); 
		}

		// 接口根目录更多操作
		/* layui.dropdown.render({
		    elem: '.tree-menu-more', // 绑定元素选择器，此处指向 class 可同时绑定多个元素
		    trigger:'hover',
		    data: [{
		      title: '导出',
		      id: 'export',
		      templet: function(d){
		    	  return '<i class="layui-icon layui-icon-download-circle"></i> ' + d.title;
		      }
		    }],
		    click: function(obj){
		      	var type=obj.id;
		      	var title = obj.title;
		      	var dataId=$(this.elem).attr('data-id');
 	 			if(type=='export'){
 	 	 			download(dataId)
 	 	 	 	}
		    }
		  }); */
		//右键目录菜单
		window.onload = function() {  
			 var treeContainer = document.getElementById('tree-container');  
		     treeContainer.addEventListener('contextmenu', function(e) {  
		 		e.preventDefault();  
		 	}); 
		     bindDownloadFunc();
		 };  

		 function bindDownloadFunc(){
			$('li .tree-node-title').off("contextmenu");
			$('li .tree-node-title').bind("contextmenu",function(e){
				var dataId=$(this).attr('data-id');
				var data = {dataId:dataId}
				var menu_data=[
					{'data':data,'type':'export','title':'导出','icon':'layui-icon-export'}
				]
				mouseRightMenu.open(menu_data,false,function(d){
					var dataId=d.data.dataId;
					var type = d.type;
					// 添加接口
					 if(type=='export'){
	 	 	 	 		download(dataId)
					 }
				});
			});
		 }
		
		// 导出
		function download(id){
			if(id){ 
				 var node=findNodeById(treeData[0],id);
				 var title=`确定导出【${node.title}】目录下的所有接口？`;
				 if(node.type=='api'){
					 title=`确定导出【${node.title}】接口？`;
				 } else if(node.type=='demo'){
					title=`确定导出【${node.title}】用例？`;
				}
				 var index=layer.confirm(title, {icon: 3,title:'导出',offset:'100px'}, function(){
					 var url='#(path)#(apiActionKey)/downloadShareApi?id='+id+'&title='+node.title;
					 window.open(url);
					 layer.close(index);
			      }, function(){

			      });
			} else {
				layer.msg("id is null");
			}
		}		
</script>  

</body>  
</html>